package nf.graph;

import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;

/**
 * Represents a path between two nodes in a {@link Graph}.
 */
public class Path
{
	private Node start;
	private Node end;
	private List<Node> steps;
	
	/**
	 * Constructs a new path.
	 */
	public Path(Node start, Node end, List<Node> steps)
	{
		this.start = start;
		this.end = end;
		this.steps = steps;
	}
	
	public Path(LinkedList<Node> steps)
	{
		this.start = steps.getFirst();
		this.end = steps.getLast();
		this.steps = steps;
	}
	
	public Path(List<Node> steps)
	{
		int size = steps.size();
		this.start = steps.get(0);
		this.end = (size <= 0) ? null : steps.get(size - 1);
		this.steps = steps;
	}
	
	Path(Node initialNode)
	{
		this.start = initialNode;
		this.end = initialNode;
		this.steps = new ArrayList<Node>(1);
		this.steps.add(initialNode);
	}

	/**
	 * Returns the starting node on the path
	 * @return Starting node on the path
	 */
	public Node getHead()
	{
	    return start;
	}
	
	/**
	 * Returns the ending node on the path
	 * @return Ending node on the path
	 */
	public Node getTail()
	{
	    return end;
	}
	
	/**
	 * Returns the list of steps in the path (including the start and end)
	 * @return List of steps in the path (including the start and end)
	 */
	public List<Node> getSteps()
	{
	    return steps;
	}
	
	/**
	 * Returns the length of the path
	 * @return Length of the path
	 */
	public int getLength()
	{
	    return steps.size();
	}
	
	
	Path extend(Node node)
	{
		ArrayList<Node> newSteps = new ArrayList<Node>(steps.size() + 1);
		
		newSteps.addAll(steps);
		newSteps.add(node);
		return new Path(start, node, newSteps);
	}
}